本节主要讲解利用 swiper 组件滚动展示信息,利用 flexbox 瀑布流布局实现浏览卡片式产品。
# 页面主体布局

当前页面的布局沿用在上一节中提到的布局。如上图所示分为两部分:头部标题栏 + 滚动浏览区域。头部标题栏 fixed 固定,内容区用 scroll-view 组件撑开整个页面。
相关代码:
<view>
<!-- 头部 -->
<uni-nav-bar fixed :status-bar="true">
头部内容
</uni-nav-bar>
<!-- 滚动区域 -->
<view class="page-content">
<mescroll-uni ref="mescroll" :fixed="false" :down="downOption" :up="upOption" @down="downCallback" @up="upCallback">
滚动区域内容
</mescroll-uni>
</view>
</view>
.page-content {
position: fixed;
top: 64px;
left: 0;
right: 0;
bottom: 0px;
/* #ifdef H5 */
top:44px; // h5 无状态栏
/* #endif */
}
在样式方面需要注意 .page-content 向下偏移一个头部标题栏的高度才可实现内容区铺满。由于不同端屏幕展示起点不同,需要做样式的调整,先看一下头部标题栏组成:
头部标题栏固定高度(64px) = 状态栏/电池栏(20px) + 标题栏(44px)
H5 的渲染起点并没有状态栏,样式需要条件编译,H5 中页面实际的标题高度展示为 44px ,因此 page-content 内容区需向下偏移 44px ,而不是 64px。

H5 未进行条件编译的状态
/* #ifdef H5 */
top:44px; // h5 无状态栏
/* #endif */
添加条件编译后,page-content 内容区偏移程度与其他端保持一致(页面正常)。里面的长列表用 mescroll-uni 上拉加载组件解决浏览交互。
# swiper 组件展示滚动信息

关于这样的信息滚动展示的功能,可能会一大波小伙伴感觉有点吃力。其实分析这一块滚动的特性,可以联想到使用 swiper 组件便能轻松实现这样的一个小功能。
相关代码:
<!-- 日期信息bar -->
<view class="date-bar flex-box">
<view class="date-bar-left">
云村热评墙 <text class="iconfont"></text>
<swiper class="date-bar-swiper" :autoplay="true" :duration="500" :circular="true" :vertical="true">
<swiper-item v-for="(item, index) in dateMsg.msgList" :key="index">
{{item.name}}
</swiper-item>
</swiper>
</view>
<view>
<view>{{dateMsg.curDate[1]}}.</view>
<view class="date-bar-num">{{dateMsg.curDate[2]}}</view>
</view>
</view>
dateMsg: {
curDate: String(new Date()).split(' '),
msgList: [
{ name: '他是我见过最年少有为的人', id: ''},
{ name: '因为一个人而失眠,这真的好吗', id: ''},
{ name: '花开花落,没有悲愁怎么是少年?', id: ''},
],
},
.date-bar-swiper{
width:430rpx;
height:40rpx;
line-height: 40rpx;
color:#d0d2d3;
font-size: 24rpx;
}
这个功能对 swiper 属性进行设置 :autoplay="true" :duration="500" :circular="true" :vertical="true",自动滚动,滑动动画时长500毫秒,采用衔接滑动,滑动方向为纵向。即可实现滚动信息展示。
# flexbox 瀑布流布局实现浏览卡片式产品
瀑布流又称瀑布流式布局,是一种比较流行的页面布局方式。与传统的分页显示不同,视觉表现为参差不齐的多栏布局。即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置。
瀑布流式布局的优点:
- 有效的降低了界面复杂度,节省了空间,不再需要臃肿复杂的页码导航链接或按钮;
- 通过向上滑动浏览,对于触屏设备非常友好,基本上所有移动设备上的信息展示都是采用这种方式,特别是购物网站;
- 滚动预加载,用户浏览时的观赏和思维不容易被打断,更高的参与度,留存更容易。

可以看上图的展示的瀑布流效果,flexbox 布局可以轻松实现,而不用使用 js 计算排版高度再插入内容等复杂的操作。我们可以把上图以 html 结构设计成:
<!-- flex 盒 -->
<view class="list-content">
<!-- 左边/第一列 -->
<view class="video-list">
<view class="video-item" v-for="(item, index) in showList.colList1"></view>
</view>
<!-- 右边/第二列 -->
<view class="video-list">
<view class="video-item" v-for="(item, index) in showList.colList2"></view>
</view>
</view>
.list-content{
display: flex;
flex-direction: row; // 水平方向排版
}
.video-list{
display: flex;
flex-direction: column; // 垂直方向排版
}
相当于 list-content 包含多列从左至右显示内容(当前为两列),单独的一列以从上到下进行排列显示。单独每一列的具体数据:
let i = 0,
list1 = [], // 左边/第一列
list2 = [], // 右边/第二列
// 如果有第三列
// list3 = [], // 第三列
// allDate 为后台获取的所有数据
while (i < allDate.length) {
list1.push(allDate[i++]);
if (i < allDate.length) {
list2.push(allDate[i++]);
}
// 如果有第三列
if (i < allDate.length) {
list3.push(allDate[i++]);
}
}
return {
list1, // 第一列
list2, // 第二列
// 如果有第三列
data3 // 第三列
};
如果使用三列的方式:
根据上面代码可以改造为多列布局,这些讲解的瀑布流布局方案,可以说是竖向瀑布流,利用 flexbox 的布局再结合下拉更新上拉加载的功能,即可实现可简单实现瀑布流布局的浏览方式。
# 底部导航栏红点与角标的设置

作为一款应用,应用内的信息提示一般会展现在底部导航栏上,Uniapp 支持设置 TabBar 上的元素以及角标等信息,统一了 h5,小程序,app 的设置角标 API。

uni.setTabBarBadge 这个 API 在 非tabbar 页面上调用会失效,因此我们需要在 common/js/util.js 封装一个方法由几个 tabbar 页面上调用。结合 Vuex 的状态管理全局管理角标信息。
相关代码:
// store/index.js
const store = new Vuex.Store({
state: {
message: {} // 角标信息
},
mutations: {
storeMessage (state, payload) { // 角标信息
state.message = {...state.message, ...payload}
}
}
})
export default store
封装公用方法,先读取存储的信息,再根据信息设置 tabbar 上的角标与文本。
// common/js/util.js
// 设置角标
setTabBarBadge (page) {
// 设置 store 红点信息
const accountMsg = store.state.message.account
const newMsg = store.state.message.newMsg || []
newMsg[page] = 0
const TempMsg = {
account: page == 4 ? 0 : accountMsg,
newMsg
}
store.commit('storeMessage', TempMsg)
// 获取 store 红点信息
const accountMsgNew = store.state.message.account
const newMsgNew = store.state.message.newMsg || []
if (accountMsgNew > 0) { // 如果有账号信息
setTimeout(() => {
// uni.setTabBarBadge 这个 API 在非tabbar页面上调用会失效。
uni.setTabBarBadge({ // 设置角标
index: 4,
text: String(accountMsgNew)
})
})
} else {
setTimeout(() => {
// 删除角标
uni.removeTabBarBadge({
index: 0,
})
})
}
newMsgNew.forEach((item, index) => { // 设置红点
if (item > 0) {
uni.showTabBarRedDot({
index
})
} else {
uni.hideTabBarRedDot({
index
})
}
})
}
在页面上调用,0 代表 tabbar 页面索引页面
onLoad() {
// 公共设置图标
this.$pubFuc.setTabBarBadge(0)
}
在进入应用的时候可以看见红点与文本的信息,并在进入当前 tabbar 页面的时候清除红点、角标,表示用户已查看提示的信息。
# 小结
- 滑动的展示都可以考虑使用 swiper 组件完成,利用好组件的功能可以达到事半功倍的的效果;
- flexbox 很容易实现瀑布流,做瀑布流需要考虑几方面的因素:图片大小,图片质量,加载速度,如果这些不能同时满足,会大大降低用户体验;
- 角标信息的设置需要在 tabbar 页面上调用。
- 本章代码 uni-course-实战开发云村页 (opens new window)。